package com.hzk.encrypte.util;

import com.hzk.encrypte.config.DataEncrypteProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @Description  类扫描工具
 * @Author hzk15
 * @Date 2022/3/29
 * @Verson 1.0
 **/
@Component
public class ScanUtils {
    private static final Log log = LogFactory.getLog(ScanUtils.class);
    private static final ResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();
    private static final MetadataReaderFactory READER_FACTORY = new SimpleMetadataReaderFactory();

    @Autowired
    DataEncrypteProperties properties;

    public ScanUtils() {
    }

    public List<Class<?>> scanEntityClasses(Class<?> annoClazz) {
        List<MetadataReader> readers = scanEntity(properties.getBasePackage());
        return scanClass(readers, (Class)null, annoClazz);
    }

    private  List<MetadataReader> scanEntity(String pattern) {
        ArrayList list = new ArrayList();

        try {
            Resource[] resources = RESOLVER.getResources(pattern);

            for(int i = 0; i < resources.length; i++) {
                Resource res = resources[i];
                MetadataReader meta = READER_FACTORY.getMetadataReader(res);
                list.add(meta);
            }
        } catch (IOException ex) {
            log.error("读取类文件时发生I/O错误。", ex);
        }

        return list;
    }

    private  List<Class<?>> scanClass(List<MetadataReader> metas, Class<?> superClazz, Class<?> annoClazz) {
        List<Class<?>> ret = new ArrayList();
        Iterator it = metas.iterator();
        MetadataReader reader;
        String annoName  = annoClazz.getName();
        Set annotationTypes;

        if (annoClazz == null) {
            return ret;
        }

        while(it.hasNext()) {
            reader = (MetadataReader)it.next();
            annotationTypes = reader.getAnnotationMetadata().getAnnotationTypes();

            if(annotationTypes.contains(annoName)) {
                String name = reader.getClassMetadata().getClassName();
                Class clazz;
                try {
                    clazz = Class.forName(name);
                    ret.add(clazz);
                } catch (ClassNotFoundException ex) {
                    log.error("类加载不成功，找不到类文件。", ex);
                }
            }
        }

        return ret;
    }
}
